package com.x.secret;

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.spec.SecretKeySpec;

/**
 * 加密过程为
 *  key为16位的16进制编码
 *  得到AES加密后的数组
 *  将数组转成BASE64字符中输出
 * qiang.hu依据周小洲的代码改善而成
 *  AES详细：
 *     AES加密模式：ECB
 *     填充方式：pkcs5padding/pkcs7padding
 *     字符集：utf8
 */
public class AESGeneralUtil
{
	
	
	private static ThreadLocal<Cipher> cipherLocal = new ThreadLocal<Cipher>();
	
	private static Map<String, String> keyValueMap = new HashMap<String, String>();
	
	private static Cipher getCipher()
	{
		Cipher cipher = null;
		try
		{
			cipher = cipherLocal.get();
      if (cipher == null) {
        cipher = Cipher.getInstance("AES");
      }
		}
		catch (Exception e)
		{
			try
			{
				throw e;
			}
			catch (Exception e1)
			{
				e1.printStackTrace();
			}
		}
		return cipher;
	}
	
	/**
	 * 加密，password为16位md5，这个要在线加密后，双方约定 password
	 * 
	 * @param content 需要加密的内容
	 * @param password 加密密码
	 * @return
	 */
	public static String encrypt(String content, String password)
	{
		try
		{
			
			SecretKeySpec key = new SecretKeySpec(password.getBytes(), "AES");// enCodeFormat的长度必须为16否则报错
			Cipher cipher = getCipher();// 创建密码器
			byte[] byteContent = content.getBytes("utf-8");
			cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
			byte[] result = cipher.doFinal(byteContent);
			return BASE64Util.encode(result); // 加密
		}
		catch (InvalidKeyException e)
		{
			e.printStackTrace();
		}
		catch (UnsupportedEncodingException e)
		{
			e.printStackTrace();
		}
		catch (IllegalBlockSizeException e)
		{
			e.printStackTrace();
		}
		catch (BadPaddingException e)
		{
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 解密
	 * 
	 * @param content 待解密内容
	 * @param password 解密密钥--一定要16位长度
	 * @return
	 */
	public static String decrypt(String content, String password) throws Exception
	{
		try
		{
			byte[] contentByte = BASE64Util.decode(content);
			SecretKeySpec key = new SecretKeySpec(password.getBytes(), "AES");
			Cipher cipher = getCipher();// 创建密码器
			cipher.init(Cipher.DECRYPT_MODE, key);// 初始化
			byte[] result = cipher.doFinal(contentByte);
			return new String(result, "UTF-8"); // 加密
		}
		catch (Exception e)
		{
			throw new RuntimeException(e.getMessage());
		}
	}
	

	
	public static void main(String[] args) throws Exception
	{
		
		ExecutorService fixThreadPool = Executors.newFixedThreadPool(20);
		for (int i = 0; i < 1; i++)
		{
			final int index = i;
			fixThreadPool.execute(new Runnable()
			{
				@Override
				public void run()
				{
					try
					{
						String source = basicData(index);
						String key = "tmall_oms1";// 要为16位md5加密的字符串
						String key2 = "oms4bytank";
						if (source.startsWith("tmall"))
						{
							String keyStr = getSecret(key); //秘钥
							//key = MD5Util.getMD5_16(key);
							String result = encrypt(source, keyStr);
							System.out.println("tmall加密:" + result);
							System.out.println("tmall解密:" + decrypt(result, keyStr));
						}
						if(source.startsWith("oms4")){
							String keyStr = getSecret(key); //秘钥
							//key = MD5Util.getMD5_16(key);
							String result = encrypt(source, keyStr);
							System.out.println("oms4加密:" + result);
							System.out.println("oms4解密:" + decrypt(result, keyStr));
						}
					}
					catch (Exception e)
					{
						System.out.println("++++++" + e.getMessage());
						e.printStackTrace();
					}
				}
			});
		}
	}

	public static String basicData(int i)
	{
		String resource = null;
		if (i % 2 == 0)
		{
			resource = "tmall{'beanName':'monitorAction','methodName':'queryWmsOutBoundOrder'}" + i;
		}
		else
		{
			resource = "oms4{'beanName':'monitorAction','methodName':'queryWmsOutBoundOrder'}" + i;
		}
		return resource;
	}
	
	public static String getSecret(String key)
	{
		String keyStr = null;
		if (keyValueMap.containsKey(key))
		{
			keyStr = keyValueMap.get(key);
		}
		else
		{
			MD5Util md5Util = new MD5Util();
			keyStr = md5Util.getMD5_16(key);
			keyValueMap.put(key, keyStr);
		}
		return keyStr;
	}
}
